package 并发编程16.Lock和Condition的使用;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author idea
 * @data 2019/2/17
 */
public class ProductQueue<T> {

    private final T[] items;

    private final Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    private int head, tail, count;

    public ProductQueue(int maxSize) {
        items = (T[]) new Object[maxSize];
    }

    public ProductQueue() {
        this(10);
    }

    public void put(T t) {
        lock.lock();
        try {
            while (count == getCapacity()) {
                //有点类似于Object.wait
                //队列满了则不写入
                System.out.println("号码已生产完毕，材料不足了");
                notFull.await();
            }
            items[tail] = t;
            if (++tail == getCapacity()) {
                tail = 0;
            }
            count++;
            //有点类似于Object.notifyAll
            notEmpty.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }


    public T take() {
        lock.lock();
        try {
            while (count == 0) {
                //相当于Object.wait
                System.out.println("号码已经抢夺完毕");
                notEmpty.await();
            }
            T out = items[head];
            //GC
            items[head] = null;
            if (++head == getCapacity()) {
                head = 0;
            }
            --count;
            notFull.signalAll();
            System.out.println("抢到了号码：" );
            return out;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            lock.unlock();
        }
    }

    public int size() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }

    public int getCapacity() {
        return items.length;
    }


    public static void main(String[] args) throws InterruptedException {
        ProductQueue<Integer> productQueue = new ProductQueue<>();
        Thread provider = new Thread(new Provider(productQueue));
        //验证队列满了是否可以再加入
        provider.start();
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Consumer[] consumers=new Consumer[100];
        //验证队列为空是否可以进行消费
        for (int i = 0; i < 100; i++) {
            consumers[i]= new Consumer(productQueue, countDownLatch);
            consumers[i].start();
        }
        System.out.println("消费者创建完毕");
        countDownLatch.countDown();

    }

}
